package com.ganeshkrishnan.globald.web.controller;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpSession;

import org.json.JSONException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.ganeshkrishnan.globald.dao.CivResourceDao;
import com.ganeshkrishnan.globald.dao.MilResourceDao;
import com.ganeshkrishnan.globald.dao.PersonDao;
import com.ganeshkrishnan.globald.dao.PersonLocationDao;
import com.ganeshkrishnan.globald.model.CivResource;
import com.ganeshkrishnan.globald.model.MilResource;
import com.ganeshkrishnan.globald.model.Person;
import com.ganeshkrishnan.globald.model.PersonLocation;
import com.ganeshkrishnan.globald.web.utils.Constants;

@Controller
@RequestMapping(value = "/resource")
public class ResourceController {
	@Autowired
	private CivResourceDao		civicDao;
	@Autowired
	private MilResourceDao		milDao;
	@Autowired
	private PersonLocationDao	personlocationdao;

	public PersonLocationDao getPersonlocationdao() {
		return personlocationdao;
	}

	public void setPersonlocationdao(PersonLocationDao personlocationdao) {
		this.personlocationdao = personlocationdao;
	}

	public MilResourceDao getMilDao() {
		return milDao;
	}

	public void setMilDao(MilResourceDao milDao) {
		this.milDao = milDao;
	}

	public CivResourceDao getCivicDao() {
		return civicDao;
	}

	public void setCivicDao(CivResourceDao civicDao) {
		this.civicDao = civicDao;
	}

	@Autowired
	private PersonDao	personDao;

	public PersonDao getPersonDao() {
		return personDao;
	}

	public void setPersonDao(PersonDao personDao) {
		this.personDao = personDao;
	}

	public ResourceController() {
	}

	/*
	 * Get number of civilians/resources param: type of civilian Add civilian param:type of civilian
	 * 
	 * FIXME Need to update the existing record. Need for consistency check Need for error/exception checking
	 */
	@RequestMapping(value = "/addcivilian", method = RequestMethod.GET)
	public @ResponseBody
	Map<String, String> addCivilian(@RequestParam int civType, @RequestParam int civNum, HttpSession session)
			throws JSONException {
		Map<String, String> map = new HashMap<String, String>();
		if (civNum < 0 || civNum > 100) {
			map.put(Constants.STATUS, "+OK");
			map.put(Constants.CODE, civNum + "");
			return map;
		}
		Long personID = (Long) session.getAttribute("personID");
		if (null == personID) {
			personID = Constants.PERSONID;
			// return "Status:-401"
			map.put(Constants.STATUS, "-ER");
			map.put(Constants.CODE, "401");
			return map;
		}
		CivResource cv = civicDao.findResourceByPerson(personID, civType);
		if (null == cv) {
			map.put(Constants.STATUS, "-OK");
			map.put(Constants.CODE, "404");
			return map;
		}
		if (cv.getCivDeployed() == civNum) {
			map.put(Constants.STATUS, "-OK");
			map.put(Constants.CODE, "304");
			return map;
		}
		cv.setCivDeployed(civNum);
		cv = civicDao.save(cv);
		map.put(Constants.STATUS, "+OK");
		map.put(Constants.CODE, "" + cv.getCivDeployed());
		return map;
	}

	@RequestMapping(value = "/getcivresource", method = RequestMethod.GET)
	public @ResponseBody
	CivResource getCivilian(@RequestParam int resType, HttpSession session) {
		Long personID = (Long) session.getAttribute("personID");
		if (null == personID) {
			personID = Constants.PERSONID;
		}
		CivResource cv = civicDao.findResourceByPerson(personID, resType);
		return cv;
	}

	@RequestMapping(value = "/getallcivresources", method = RequestMethod.GET)
	public @ResponseBody
	Map<String, String> getAllCivilian(HttpSession session) {
		Map<String, String> map = new HashMap<String, String>();
		Long personID = (Long) session.getAttribute("personID");
		if (null == personID) {
			personID = Constants.PERSONID;
			map.put(Constants.STATUS, "-ER");
			map.put(Constants.CODE, "401");
			return map;
		}
		Person player = personDao.get(personID);
		Set<CivResource> resources = player.getResource();
		for (CivResource civResource : resources) {
			if (civResource.getResType() > civResource.DOLLAR) {
				continue;
			}
			/**
			 * FIXME Logic to increment resource if it last update is more than
			 * 30 minutes goes here Change to use non-deprecated methods
			 */

			Date olddate = civResource.getResourceUpdated();

			Date newdate = new Date();
			long difftime = newdate.getTime() - olddate.getTime();
			long diffHours = difftime / (60 * 60 * 1000);

			if (diffHours > 0) {

				if (civResource.getResType() == civResource.DOLLAR) {
					long diffdays = diffHours / 24;
					if (diffdays < 1)
						continue;

					int totalLocations = player.getLocation().size();
					civResource.setResAvailable(civResource.getResAvailable() + (totalLocations * diffdays));

				} else {
					civResource.setResAvailable(civResource.getResAvailable()
							+ (civResource.getCivDeployed() * diffHours));
				}
				civResource.setResourceUpdated(newdate);
				civResource = civicDao.save(civResource);
			}
			map.put("res" + civResource.getResType(), String.valueOf(civResource.getResAvailable()));

		}

		map.put(Constants.STATUS, "+OK");
		return map;
	}

	@RequestMapping(value = "/addmil", method = RequestMethod.GET)
	public @ResponseBody
	Map<String, String> addMil(@RequestParam int milType, @RequestParam int milNum, HttpSession session) {
		Map<String, String> map = new HashMap<String, String>();
		Long personID = (Long) session.getAttribute("personID");
		if (null == personID) {
			personID = Constants.PERSONID;
			// return "Status:-401"
			map.put(Constants.STATUS, "-ER");
			map.put(Constants.CODE, "401");
			return map;
		}
		MilResource mil = milDao.findResourceByPerson(personID, milType);
		if (null == mil) {
			//some smart ass is trying to inject something?
			map.put(Constants.STATUS, "-ER");
			map.put(Constants.CODE, "404");
			return map;
		}
		if (mil.getMilAvailable() == milNum) {
			map.put(Constants.STATUS, "-ER");
			map.put(Constants.CODE, "304");
			return map;
		}

		Person p = personDao.get(personID);
		Set<CivResource> set = p.getResource();

		for (CivResource civResource : set) {
			int cost = ((9 - civResource.getResType()) * 100) * (milType + 1);
			long newvalue = civResource.getResAvailable() - cost;
			if (newvalue < 0) {
				map.put(Constants.STATUS, "-ER");
				map.put(Constants.CODE, "404");
				return map;
			}
			civResource.setResAvailable(newvalue);
			set.add(civResource);
		}
		p.setResource(set);
		personDao.save(p);

		mil.setMilAvailable(milNum);
		mil = milDao.save(mil);

		map.put(Constants.STATUS, "+OK");
		map.put(Constants.CODE, "" + mil.getMilAvailable());
		return map;
	}

	// initializing method
	@RequestMapping(method = RequestMethod.GET)
	public String getCreateForm(Model model, HttpSession session) {
		Long personID = (Long) session.getAttribute("personID");
		if (null == personID) {
			personID = Constants.PERSONID;
			return "redirect:/country.html";
		}
		Person p = personDao.get(personID);

		PersonLocation pl = personlocationdao.findHomeCityByPersonID(p.getId());
		model.addAttribute("homeLat", pl.getLatitude());
		model.addAttribute("homeLon", pl.getLongitude());
		model.addAttribute("person", p);
		int ccode = p.getCountryCode().getID();
		model.addAttribute("homeCountry", ccode);
		String en = "PK";
		/**
		 * This should be moved to Db as a field in country detail!
		 */
		switch (ccode) {
			case 1:
				break;
			case 2:
				en = "IN";
				break;
			case 13:
				en = "IN";
				break;
			case 11:
				en = "PK";
				break;
		}
		model.addAttribute("enemyCountry", en);
		return "start";
	}

	// ----------------internal helpers
	//------------ experimental features
	@RequestMapping(value = "/getperson", method = RequestMethod.GET)
	public @ResponseBody
	Person getPerson(@RequestParam int personid, HttpSession session) {
		Long personID = (Long) session.getAttribute("personID");
		if (null == personID) {
			return null;
		}
		Person p = personDao.get(personID);
		return p;
	}

	@RequestMapping(value = "/addresource", method = RequestMethod.GET)
	public @ResponseBody
	CivResource addResource(@RequestParam int resType, @RequestParam int resNum) {
		CivResource cv = new CivResource();
		cv.setResAvailable(resNum);
		cv.setResType(resType);
		cv = civicDao.UpdateResource(cv);
		return cv;
	}

	@RequestMapping(value = "/getmil", method = RequestMethod.GET)
	public @ResponseBody
	MilResource getMil(@RequestParam int resType, HttpSession session) {
		Long personID = (Long) session.getAttribute("personID");
		if (null == personID) {
			personID = Constants.PERSONID;
		}
		MilResource mil = milDao.get(personID);
		return mil;
	}
}
